package com.quanxiaoha.weblog.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.quanxiaoha.weblog.common.domain.dos.CountNode;
import com.quanxiaoha.weblog.common.domain.entity.*;
import com.quanxiaoha.weblog.common.domain.mapper.ArticleMapper;
import com.quanxiaoha.weblog.common.domain.mapper.ScheduleCountMapper;
import com.quanxiaoha.weblog.common.domain.mapper.ScheduleHabitMapper;
import com.quanxiaoha.weblog.common.domain.mapper.ScheduleRecordMapper;
import com.quanxiaoha.weblog.common.domain.query.CensusQuery;
import com.quanxiaoha.weblog.common.domain.query.CountQuery;
import com.quanxiaoha.weblog.common.domain.vo.*;
import com.quanxiaoha.weblog.common.entity.ScheduleHabitItem;
import com.quanxiaoha.weblog.common.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ScheduleCountServiceImpl extends ServiceImpl<ScheduleCountMapper, ScheduleCount> implements ScheduleCountService {

    @Resource
    ThreadPoolTaskExecutor taskExecutor;

    @Autowired
    private IScheduleSkillService scheduleSkillService;

    @Autowired
    private IScheduleSkillStageService scheduleSkillStageService;

    @Autowired
    private IScheduleHabitItemService  scheduleHabitItemService;

    @Autowired
    private ScheduleHabitMapper scheduleHabitMapper;

    @Autowired
    private ScheduleRecordMapper scheduleRecordMapper;

    @Autowired
    private ArticleMapper articleMapper;

    @Override
    public List<CountVo> recommend(CountQuery countQuery) {

        LambdaQueryWrapper<ScheduleCount> qw = new LambdaQueryWrapper<>();
        if (Objects.isNull(countQuery.getTagId())) return null;

        qw.eq(ScheduleCount::getTagId, countQuery.getTagId());
        if(Objects.nonNull(countQuery.getScheduleName())){
            qw.like(ScheduleCount::getRecordName, countQuery.getScheduleName());
        }
        qw.orderByDesc(ScheduleCount::getCount);
        qw.last("limit 10");
        List<ScheduleCount> list = this.list(qw);
        List<CountVo> countVos = BeanUtil.copyToList(list, CountVo.class);
        return countVos;
    }

    @Override
    public List<CountVo> reverseRecommend(CountQuery countQuery) {

        LambdaQueryWrapper<ScheduleCount> qw = new LambdaQueryWrapper<>();
        if(Objects.nonNull(countQuery.getScheduleName())){
            qw.like(ScheduleCount::getRecordName, countQuery.getScheduleName());
        }
        qw.orderByDesc(ScheduleCount::getCount);
        qw.ne(ScheduleCount::getTagId, 0);
        qw.last("limit 10");
        List<ScheduleCount> list = this.list(qw);
        List<CountVo> countVos = BeanUtil.copyToList(list, CountVo.class).stream()
                .collect(Collectors.toMap(
                        CountVo::getRecordName,      // Key 提取函数（去重字段）
                        Function.identity(),
                        (oldVal, newVal) -> oldVal // 冲突时保留旧值
                ))
                .values()
                .stream()
                .collect(Collectors.toList());;
        return countVos;
    }

    @Override
    @Async("taskExecutor")
    public void saveCount(ScheduleRecord scheduleRecord) {

        LambdaUpdateWrapper<ScheduleCount> wq = new LambdaUpdateWrapper<>();
        wq.eq(ScheduleCount::getRecordName,scheduleRecord.getScheduleName());
        wq.eq(ScheduleCount::getTagId,scheduleRecord.getTagId());
        List<ScheduleCount> list = this.list(wq);
        if(list.size()>0){
            ScheduleCount scheduleCount = list.get(0);
            scheduleCount.setCount(scheduleCount.getCount()+1);
            this.updateById(scheduleCount);
        }else {
            ScheduleCount scheduleCount = new ScheduleCount();
            scheduleCount.setRecordName(scheduleRecord.getScheduleName());
            scheduleCount.setCount(1);
            scheduleCount.setCreateTime(LocalDateTime.now());
            scheduleCount.setUpdateTime(LocalDateTime.now());
            scheduleCount.setTagId(scheduleRecord.getTagId());
            this.save(scheduleCount);
        }

        if(scheduleRecord.getTagId()==2){
            LambdaUpdateWrapper<ScheduleCount> wq2 = new LambdaUpdateWrapper<>();
            wq2.eq(ScheduleCount::getRecordName,scheduleRecord.getMotivation());
            wq2.eq(ScheduleCount::getTagId,0);
            List<ScheduleCount> list2 = this.list(wq2);
            if(list2.size()>0){
                ScheduleCount scheduleCount = list2.get(0);
                scheduleCount.setCount(scheduleCount.getCount()+1);
                this.updateById(scheduleCount);
            }else {
                ScheduleCount scheduleCount = new ScheduleCount();
                scheduleCount.setRecordName(scheduleRecord.getMotivation());
                scheduleCount.setCount(1);
                scheduleCount.setCreateTime(LocalDateTime.now());
                scheduleCount.setUpdateTime(LocalDateTime.now());
                scheduleCount.setTagId(0);
                this.save(scheduleCount);
            }
        }
    }

    @Override
    public HomeDetailVo homeDetails(CensusQuery query) {

        List<ScheduleCount> studies = this.list(new LambdaQueryWrapper<ScheduleCount>()
                .eq(ScheduleCount::getTagId, 1)
                .gt(ScheduleCount::getCount,1));
        List<ScheduleCount> wastes = this.list(new LambdaQueryWrapper<ScheduleCount>()
                .eq(ScheduleCount::getTagId, 2)
                .gt(ScheduleCount::getCount,1));
        List<CountNode> studiesNodes = buildTree(BeanUtil.copyToList(studies, CountNode.class));
        List<CountNode> wastesNodes = buildTree(BeanUtil.copyToList(wastes, CountNode.class));
        studiesNodes.sort(Comparator.comparing(CountNode::getCount).reversed());
        wastesNodes.sort(Comparator.comparing(CountNode::getCount).reversed());
        log.info("工作学习：{}",studiesNodes);
        log.info("浪费时间：{}",wastesNodes);

        List<ScheduleSkill> list = scheduleSkillService.list(new LambdaQueryWrapper<ScheduleSkill>().eq(ScheduleSkill::getIsCompleted, 1));
        List<ScheduleSkillVo> skillVos = BeanUtil.copyToList(list, ScheduleSkillVo.class);
        skillVos.forEach(scheduleSkillVo -> {
            scheduleSkillVo.setStageVos(scheduleSkillStageService.getStageList(scheduleSkillVo.getId()));
        });
        HomeDetailVo homeDetailVo = new HomeDetailVo();
        homeDetailVo.setWastesNodes(wastesNodes);
        homeDetailVo.setStudiesNodes(studiesNodes);
        homeDetailVo.setSkillVos(skillVos);
        return homeDetailVo;
    }

    @Override
    public HomeHeaderVo homeHeader(CensusQuery query) {

        HomeHeaderVo homeHeaderVo = new HomeHeaderVo();
        //新卡片数量
        long count = articleMapper.selectCount(new LambdaQueryWrapper<Article>()
                .lt(Article::getReadNum, 5));
        homeHeaderVo.setCardNum((int)count);
        //习惯数量
        // 获取当天的 00:00:00 和 23:59:59.999
        LocalDateTime start = LocalDate.now().atStartOfDay(); // 当天开始时间
        LocalDateTime end = LocalDateTime.of(LocalDate.now(), LocalTime.MAX); // 当天结束时间

        // 使用 LambdaQueryWrapper（避免硬编码字段名）
        LambdaQueryWrapper<ScheduleHabitItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.between(ScheduleHabitItem::getCreateTime, start, end); // 字段名通过方法引用指定
        wrapper.orderByAsc(ScheduleHabitItem::getCompletedCount);
        // 执行查询
        List<ScheduleHabitItem> list = scheduleHabitItemService.list(wrapper);
        homeHeaderVo.setHabits(list);
        //今日工作时长

        // 获取当天0点
        LocalDateTime inputDateTime = LocalDateTime.now();
        LocalDateTime startOfDay = inputDateTime.with(LocalTime.MIN); // 等价于00:00:00

        // 获取当天24点（精确至纳秒级最后一刻）
        LocalDateTime endOfDay = inputDateTime.with(LocalTime.MAX); // 23:59:59.999999999


        List<ScheduleRecord> records = scheduleRecordMapper.selectList(new LambdaQueryWrapper<ScheduleRecord>()
                .eq(ScheduleRecord::getTagId, 1)
                .ge(ScheduleRecord::getCreateTime, startOfDay)  // create_time > startTime
                .lt(ScheduleRecord::getCreateTime, endOfDay));
        records.forEach(x -> {
            Duration duration = Duration.between(x.getCreateTime(), x.getEndTime());
            long minutes = duration.toMinutes(); // 直接获取总分钟差[3,7](@ref)
            homeHeaderVo.setMinutes((int)minutes + homeHeaderVo.getMinutes());
        });
        return homeHeaderVo;
    }

    public static List<CountNode> buildTree(List<CountNode> paths) {
        Map<String, CountNode> nodeMap = new HashMap<>();
        List<CountNode> roots = new ArrayList<>();

        for (CountNode path : paths) {
            path.setName(path.getRecordName());
            String[] parts = path.getRecordName().split("/");
//            if (parts.length < 2) continue; // 跳过单节点路径

            CountNode currentParent = null;
            String currentPath = "";

            for (int i = 0; i < parts.length; i++) {
                String name = parts[i];
                currentPath = (i == 0) ? name : currentPath + "/" + name;
                CountNode node = null;
                if(i==parts.length-1){
                    node = nodeMap.computeIfAbsent(currentPath, k -> path);

                    String pCurrentPath = "";
                    for (int j = 0; j < i; j++) {
                        String pName = parts[j];
                        pCurrentPath = (j == 0) ? pName : pCurrentPath + "/" + pName;
                        CountNode countNode = nodeMap.get(pCurrentPath);
                        if(countNode!=null){
                            countNode.setCount(node.getCount() + countNode.getCount());
                        }
                    }
                }else{
                    node = nodeMap.computeIfAbsent(currentPath, k -> new CountNode(name));
                }

                // 根节点处理
                if (i == 0 && !roots.contains(node)) {
                    roots.add(node);
                }

                // 建立父子关系
                if (currentParent != null && !currentParent.getChildren().contains(node)) {
                    currentParent.addChild(node);
                }
                currentParent = node; // 更新为当前节点
            }
        }
        return roots;
    }

}
